API call IBM Watson Natural Language Understanding-xq - Python or Postman - python-3.x

I'm struggling to connect to the IBM Watson API for Natural Language Understanding.
I've added it to the Resource list in my IAM account. I've got to the page with an example POST request to connect to the API, and I can't seem to authenticate. I've blanked out the API key from this request but in the pages the key is supplied so I'm struggling to see why it's not working
curl -X POST -u "#######" \
-H "Content-Type: application/json" \
-d '{ "text": "I still have a dream. It is a dream deeply rooted in the
American dream. I have a dream that one day this nation will rise up and
live out the true meaning of its creed: \"We hold these truths to be
self-evident, that all men are created equal.\"", "features": {
"sentiment": {}, "keywords": {} }}' \
"https://gateway-lon.watsonplatform.net/natural-language-
understanding/api/v1/analyze?version=2018-03-19"
I've tried pasting this into Postman but I just get a 401 Unauthorized response, which makes me think it's something in the account pages of the IAM, but they've chnage the interface and not update the documentation, and I'm going round in circles because the instructions don't match the menus.
Any pointers would be appreciated. I intend to query through Python, so I'm hoping once I can get past the authentication issue it's as simple as copying the Python code out of Postman

Your -u credentials should be:
-u "apikey:#######"
As per the API documentation -
https://cloud.ibm.com/apidocs/natural-language-understanding#authentication

Somehow the API credentials were not being recognised. I must have done something wrong in the initial IAM setup, which meant that when I deleted the credentials, re-created them and then copied the new key ... everything immediately started working. Complete mystery as to why but hopefully this helps someone. Here are the instructions I followed
https://console.bluemix.net/docs/services/natural-language-understanding/getting-started.html#getting-started-tutorial
I used the SDK as suggested by Simon O'Doherty
It might also be related to me having gone into the "Manage" >> "Account" and deleted any Access Groups and Service IDs I'd attempted to create by following the "Getting Started with IAM" instructions from here, which I suspect might have been what confused me
IAM getting started (not required)

Related

csrf token in bluemix deployed node instance

Hi I used the deploy to bluemix button at the top right of this page
https://alchemy-language-demo.mybluemix.net/?cm_mc_uid=69990450306114782046823&cm_mc_sid_50200000=1478206651
to create an Alchemy language node server. It runs ok -
https://alchemylanguage-nodejs-encekxdev-216.mybluemix.net/
but when I try to post to it using postman I get the response 'internal server error'.
Checking the server logs, it seems to respond to the request with
code: 'EBADCSRFTOKEN', error: 'invalid csrf token'
Even if I try to send the csrf from the webpage version of the site, it still doesn't work.
I feel like I have missed something in the configuration of the server but don't know what. I'm not great with servers etc so sorry if this is super basic.
EDIT - I should mention I have also tried sending an apikey in the request which I got from the service credentials section in the alchemy service bit off the dashboard but the same error occurs.
EDIt - The call to the API I am making looks like this:
POST https://alchemylanguage-nodejs-encekxdev-216.mybluemix.net/api/keywords
with headers:
text: 'this is some dummy text I have made'
I have also tried adding apikey to the headers.
Thanks.
You do not POST your application, you have to POST to the API.
Here is the link with API URL and various samples:
http://www.ibm.com/watson/developercloud/alchemy-language/api/v1
For example, here is a curl request for keywords:
curl -X POST \
-d "outputMode=json" \
-d "url=http://www.twitter.com/ibmwatson" \
"https://gateway-a.watsonplatform.net/calls/url/URLGetRankedKeywords?apikey=$API_KEY"
Make sure you export $API_KEYto your environment before running the command above. You can find the $API_KEY in the AlchemyAPI instance you created in Bluemix.

Instagram API: The access_token provided is invalid

I have registred a sandbox user. Now I am trying to use it, but I recieve "The access_token provided is invalid".
Sample request:
https://api.instagram.com/v1/users/searchq=abc&count=2&client_id=7b67cff1a7ab462881298434c08b5ab8
It was working in live mode, but I can't find why it isn't working in sandbox.
You need to check for requirements Scope for API you are using and if it's need and Authentications "Valid access Token". where also had some changes.
basic - to read a user’s profile info and media
public_content to read any public profile info and media on a user’s behalf
follower_list to read the list of followers and followed-by users
comments - to post and delete comments on a user’s behalf
relationships - to follow and unfollow accounts on a user’s behalf
likes - to like and unlike media on a user’s behalf
And take look about **Sandbox API behavior of your application not life yet :**
API Behavior
The behavior of the API when you are in sandbox mode is the same as when your app is live, but comes with the following restrictions:
Data is restricted to sandbox users and the 20 most recent media from each sandbox user
Reduced API rate limits
The first point is important and it means that the API behaves as if the only users on Instagram were your sandbox users, and the only media ever posted were the last 20 for each of these users.
For example, if you query the /users/{user-id}/ endpoint and the {user-id} is a sandbox user, then you will get the normal API response; but if the {user-id} is not a sandbox user, you will get a APINotFound error.
Good luck
For me the access token Instagram generate is too short: they gave me something like this:
d2c387d768ec4d619306807c53bbf92b
it should be:
2940736713.1677ed0.31bb22b2b0f84befacc79c6afd025134
I used this site to generate it:
http://instagram.pixelunion.net
I found it when solving the same problem with access by access_token
Here is official faq how to get access_token
You just should go through following steps (link to Instagram API documentation https://www.instagram.com/developer/authentication/):
1.Request the CODE
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code
change CLIENT_ID to you client id (you could get it here https://www.instagram.com/developer/clients/manage/ )
change REDIRECT-URI to your redirect_uri from tab security in client settings(open link above and tap to 'manage' button). I Used this one https://meyerweb.com/eric/tools/dencoder/ Encode url here and paste te result instead REDIRECT-URI
After you prepared it cope ready link to adress bar in your browser and run
2. Get the CODE
Browser ask you a premissons and redirect you to callback url with the code in the end. It will be look like this in adress bar:
http://yoursite.some/?code=d8af5619af6853d4ad11b4dd5f1ef17e
In this example your code is d8af5619af6853d4ad11b4dd5f1ef17e
Save it. You should use it in access_token request below
3. Make an access_token request
Open terminal and use curl:
curl -F 'client_id=CLIENT_ID' \
-F 'client_secret=CLIENT_SECRET' \
-F 'grant_type=authorization_code' \
-F 'redirect_uri=AUTHORIZATION_REDIRECT_URI' \
-F 'code=CODE' \
https://api.instagram.com/oauth/access_token
Change CLIENT_ID, CLIENT_SECRET, AUTHORIZATION_REDIRECT_URI and CODE to your own data and run it.
Curl return you JSON with access_token like this:
{
"access_token": "fb2e77d.47a0473320504cb3ab4a1f626d174d2d",
"user": {
"id": "1576583",
"username": "some",
"full_name": "Some",
"profile_picture": "..."
}
}
Well done! In this example fb2e77d.47a0473320504cb3ab4a1f626d174d2d is your access_token. Copy access_token value, use it in your app and enjoy you coding! :)
My issue was using v1 of Instafeed.js, rather than v2.
Once I switched to v2, everything started working.
<script src="/instafeed/dist/instafeed.min.js"></script>
<script src="https://ig.instant-tokens.com/users/.../instagram/.../token.js?userSecret=..."></script>
<div id="instafeed" class="instagram-feed">
</div>
<script>
(function(){
console.log(InstagramToken);
window.addEventListener('load', function () {
var feed = new Instafeed({
accessToken: InstagramToken,
});
feed.run();
});
})();
</script>
You haven't specified an access_token for your request.

Can't get client-credentials access token to authorize Power BI

I'm trying to use the Power BI REST API, using an access token acquired with the "client credentials" method, but I keep getting 403 Forbidden on my requests.
My code follows the pattern demonstrated in this AzureAD sample. In fact, to isolate this problem, I'm running that sample code (with my own values in the parameters.json, of course):
{
expiresIn: 3599,
tokenType: 'Bearer',
expiresOn: Tue Sep 01 2015 16:56:07 GMT-0500 (CDT),
resource: '00000002-0000-0000-c000-000000000000',
accessToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9.eyJhdWQiOiIwMDAwMDAwMi0wMDAwLTAwMDAtYzAwMC0wMDAwMDAwMDAwMDAiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC8xM2QxNzIwNC0wZGU2LTQ1NzQtOTgzYS05NjFhYjk0M2M3Y2UvIiwiaWF0IjoxNDQxMTQwNjcwLCJuYmYiOjE0NDExNDA2NzAsImV4cCI6MTQ0MTE0NDU3MCwidmVyIjoiMS4wIiwidGlkIjoiMTNkMTcyMDQtMGRlNi00NTc0LTk4M2EtOTYxYWI5NDNjN2NlIiwib2lkIjoiYzM1ZWQyYTktYTYzZS00YzAwLThmYmYtY2FlYjlmZjYwMjYwIiwic3ViIjoiYzM1ZWQyYTktYTYzZS00YzAwLThmYmYtY2FlYjlmZjYwMjYwIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvMTNkMTcyMDQtMGRlNi00NTc0LTk4M2EtOTYxYWI5NDNjN2NlLyIsImFwcGlkIjoiNDQ2Y2Y5OTItMDQzYS00YjgxLWJhYzQtY2RlZWYyNGFhNzFjIiwiYXBwaWRhY3IiOiIxIn0.YTGJfdW1wP09bDHwwsv3FPAmEpmQdc_kifvgY-1KjhkZWANfYtd050wfeZdNgMUeSPZyFdWnoBjnJ4xrlDtnsADwV1Grr6TXYcymPLofbY-xy0cjyvzxTmM11DJ9XN8A4tkgvK0jtR-YyIjPw5EKJSKyeEbD9U3mWsE_gu7IzKzXl8e-dfVAqRYS6WHZy6_0FaNmppPDls5s_QIPOHofFSiWVISw41Mz0fQnP2QEGyceOCvKYJtrUOCDwfVuwFS-gSLmYvEGOJfmIjftP3srda0JPirVzBeU0IFJJ1KW81kE5cfKw1KkBB04VVetRUs_7HqloYaKKiTybauhXAodRQ',
isMRRT: true,
_clientId: '[snip]',
_authority: 'https://login.windows.net/[snip]'
}
When I use that access token in a curl request, as follows, I get a 403:
curl -vv -X GET https://api.powerbi.com/v1.0/myorg/datasets -H"Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9.eyJhdWQiOiIwMDAwMDAwMi0wMDAwLTAwMDAtYzAwMC0wMDAwMDAwMDAwMDAiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC8xM2QxNzIwNC0wZGU2LTQ1NzQtOTgzYS05NjFhYjk0M2M3Y2UvIiwiaWF0IjoxNDQxMTQwNjcwLCJuYmYiOjE0NDExNDA2NzAsImV4cCI6MTQ0MTE0NDU3MCwidmVyIjoiMS4wIiwidGlkIjoiMTNkMTcyMDQtMGRlNi00NTc0LTk4M2EtOTYxYWI5NDNjN2NlIiwib2lkIjoiYzM1ZWQyYTktYTYzZS00YzAwLThmYmYtY2FlYjlmZjYwMjYwIiwic3ViIjoiYzM1ZWQyYTktYTYzZS00YzAwLThmYmYtY2FlYjlmZjYwMjYwIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvMTNkMTcyMDQtMGRlNi00NTc0LTk4M2EtOTYxYWI5NDNjN2NlLyIsImFwcGlkIjoiNDQ2Y2Y5OTItMDQzYS00YjgxLWJhYzQtY2RlZWYyNGFhNzFjIiwiYXBwaWRhY3IiOiIxIn0.YTGJfdW1wP09bDHwwsv3FPAmEpmQdc_kifvgY-1KjhkZWANfYtd050wfeZdNgMUeSPZyFdWnoBjnJ4xrlDtnsADwV1Grr6TXYcymPLofbY-xy0cjyvzxTmM11DJ9XN8A4tkgvK0jtR-YyIjPw5EKJSKyeEbD9U3mWsE_gu7IzKzXl8e-dfVAqRYS6WHZy6_0FaNmppPDls5s_QIPOHofFSiWVISw41Mz0fQnP2QEGyceOCvKYJtrUOCDwfVuwFS-gSLmYvEGOJfmIjftP3srda0JPirVzBeU0IFJJ1KW81kE5cfKw1KkBB04VVetRUs_7HqloYaKKiTybauhXAodRQ"
Wondering if that curl request was flawed somehow, I snooped out an access token “the wrong way” via browser webtools, and the above works fine, returning a 200 and a JSON response listing my datasets.
I did also notice that the return code is 403 (forbidden), not 401 (unauthorized), so I wondered if the authorization was okay but the permissions on the Power BI side were wrong. But I also get 403 when I use any garbage text for the access token (e.g., Authorization: Bearer foo), so I discarded that theory.
So. I think I have a valid test, and I’m getting what I think is a valid access token (from that client-credentials-sample.js code), but it’s still not working. What am I missing?
With the assistance of some Microsoft folks (thanks, Jon Gallant & Josh Caplan), I've learned that authenticating with an OAuth client-credentials flow, as I was doing with that JavaScript sample, provides insufficient access. To use Power BI, authentication needs to be based on a particular user.
I tried using:
the similar JavaScript sample username-password-sample.js
a resource value of https://analysis.windows.net/powerbi/api (thanks, slugslog)
adding username and password to the parameters.json
That got me closer, but I was still getting a 400 response: "error_description":"AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'. …".
A hack to the adal-node library (hardcoding the client secret, i.e., oauthParameters[OAuth2Parameters.CLIENT_SECRET] = "my-client-secret"; after line 217 of token-request.js) was enough to get back an access token which works in the Authorization header for my original curl call.
Of course hardcoding that value in there isn't my final solution. I don't plan to use the adal-node library, anyway. But as far as this proof-of-concept for this authentication case goes, that's the answer I came to.
Make sure that your app that you registered with AAD has the read write all datasets permission. That should solve the problem.
This is not an answer but one step forward in the debug process. I think the resource for which the token is requested should be "https://analysis.windows.net/powerbi/api". I've seen these in multiple references; one of them is linked below. Even after changing this, I still get a 403. As the OP mentioned if we use the accessToken from the powerBI portal, everything works.
So I tried this with my own app, the following command works (for me):
curl -vv -X GET https://api.powerbi.com/v1.0/myorg/datasets -H"Authorization: Bearer ey....qqqq"
BTW, the extra "v" after -v seems redundant.
So what I can conclude is that your application is missing the required permissions to call Power BI's APIs.
One thing you might try is grab one of our samples, create a new application in AAD for it, and then see if the authorization token works for it. Here's a good one to try: https://github.com/PowerBI/Integrate-a-tile-into-an-app

Getting pronunciation of a word using Google Translate API

I am trying to save the pronunciation of a French word into a .wav or .mp3 file.
I was wondering if there was anywhere on the Google Translate API (since it has a pronunciation functionality) that allows me to achieve this objective. Other libraries would work too.
Since this question was asked, it's gotten much harder to "scrape" MP3s from Google Translate, but Google has (finally) set up a TTS API. Interestingly it is billed in input characters, with the first 1 or 4 million input characters per month being free (depending on whether you use WaveNet or old school voices)
Nowadays to do this using gcloud on the command line (versus building this into an app) you would do roughly as follows (I'm paraphrasing the TTS quick start). You need base64, curl, gcloud, and jq for this walkthrough.
Create a project on the GCP console, or run something like gcloud projects create example-throwaway-tts
Enable billing for the project. Do this even if you don't intend to exceed the freebie quota.
Use the GCP console to enable the TTS API for the project you just set up.
Use the console again, this time to make a new service account.
Use any old name
Don't give it a role. You'll get a warning. This is okay.
Select key type JSON if it isn't already selected
Click Create
Hold onto the JSON file that your browser downloads
Set an environment variable to point at that file, e.g. export GOOGLE_APPLICATION_CREDENTIALS="~/Downloads/service-account-file.json"
Get the appropriate access token:
Tell gcloud to use that new project: gcloud config set project example-throwaway-tts
Set a variable TTS_ACCESS_TOKEN=gcloud auth application-default print-access-token
Put together a JSON request. I'll give an example below. For this example we'll call it request.json
Lastly, run the following
curl \
-H "Authorization: Bearer "$TTS_ACCESS_TOKEN \
-H "Content-Type: application/json; charset=utf-8" \
--data-raw #request.json \
"https://texttospeech.googleapis.com/v1/text:synthesize" \
| jq '.audioContent' \
| base64 --decode > very_simple_example.mp3
What this does is to
authenticate using the default access token for the project you set up
set the content type to JSON (so that jq can extract the payload)
use request.json as the data to send using curl's --data-raw flag
extract the value of audioContent from the response
base64 decode that content
save the whole mess as an MP3
Contents of request.json follow. You can see where to insert your desired text, adjust the voice or change output formats via audioConfig:
{
'input':{
'text':'very simple example'
},
'voice':{
'languageCode':'en-gb',
'name':'en-GB-Standard-A',
'ssmlGender':'FEMALE'
},
'audioConfig':{
'audioEncoding':'MP3'
}
}
Original Answer
As Hugolpz alludes, if you know the word or phrase you want (via a previous Translate API call), you can get MP3s from a URL like http://translate.google.com/translate_tts?ie=UTF-8&q=Bonjour&tl=fr
Note that &tl=fr ensures that you get French instead of the default English.
You will need to rate-limit yourself, but if you're looking for a small number of words or phrases you should be fine.
Similar functionality is provided by the Speech Synthesis API (under development). Third-party libraries are already there, such as ResponsiveVoice.JS.

CouchDB Authorization on a Per-Database Basis

I'm working on an application supported by CouchDB. Essentially, I want to create a database for each individual user of my app. To accomplish this, the admin user will create the database, but going forward, the user will need to access their database (using HTTP Auth over SSL). I've been having a hell of a time figuring this out.
The best resource I have found is in the CouchDB wiki, at this link:
http://wiki.apache.org/couchdb/Security_Features_Overview#Authorization
It suggests that you can set per-database authorization by creating a document called "_security" to which you add a hash of admins and readers. When I attempt to create that document, the message I get back is "Bad special document member: _security".
$ curl -X GET http://localhost:5984
{"couchdb":"Welcome","version":"1.0.1"}
Any help would be appreciated!
Cheers,
Aaron.
There should be no problem with that aproach.
Let's say you have a database "test", and have an admin account already:
curl -X PUT http://localhost:5984/test -u "admin:123"
Now you can create a _security document for it:
curl -X PUT http://localhost:5984/test/_security -u "admin:123" -d '{"admins":{"names":[], "roles":[]}, "readers":{"names":["joe"],"roles":[]}}'
Them only the user "joe" will be able to read the database. To create the user you must have already the sha1 hashed password:
curl -X POST http://localhost:5984/_users -d '{"_id":"org.couchdb.user:joe","type":"user","name":"joe","roles":[],"password_sha":"c348c1794df04a0473a11234389e74a236833822", "salt":"1"}' -H "Content-Type: application/json"
This user have the password "123" hashed using sha1 with salt "1" (sha1("123"+"1")), so he can read the database:
curl -X GET http://localhost:5984/test -u "joe:123"
He can read any document now on that database, and no other user (but him and admin) can.
UPDATED: Writer security
The above method issues the reader problem, but the reader permission here actually mean "read/write common docs", so it allows to write docs except for design-docs. The "admin"s in the _security doc are allowed to write do design-docs in this database.
The other approach, as taken from your own answer, is the "validate_doc_update", you can have a validate_doc_update as follow in a file:
function(new_doc, old_doc, userCtx) {
if(!userCtx || userCtx.name != "joe") {
throw({forbidden: "Bad user"});
}
}
And push it into a couchdb design:
curl -X PUT http://localhost:5984/test/_design/security -d "{ \"validate_doc_update\": \"function(new_doc,doc,userCtx) { if(userCtx || userCtx.name != 'joe') {throw({forbidden: 'Bad user'})}}\"}" --user 'admin:123'
Them "joe" can write to the database using Basic Authentication:
curl -X PUT http://localhost:5984/test/foobar -d '{"foo":"bar"}' -u 'joe:123'
As you also addressed you can use the _session api to get a cookie for authentication:
curl http://localhost:5984/_session -v -X POST -d 'name=joe&password=123' -H "Content-Type: application/x-www-form-urlencodeddata"
This will return a header like:
Set-Cookie: AuthSession=am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz; Version=1; Path=/; HttpOnly
So you can include the cookie "AuthSession=am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz" in your next requests and they will be authenticated.
I've been doing more research and testing, and I want to summarize where I've gotten to, and what still isn't working for me.
First off, apologies for those who read this question: I was looking for ways to set permissions for people to write, not read, the database. It turns out be be a big difference: the techniques for creating a "reader" are entirely different from creating a "writer" (that term actually doesn't exist, though I wonder why).
In brief: you have to add a user to the _users database, which is a list of the users that have access to any database in your CouchDB instance. I was able to do that by issuing a command similar to:
curl -X PUT http://admin:password#localhost:5984/_users/org.couchdb.user:username -d '{"type":"user", "hashed_password":"2bf184a2d152aad139dc4facd7710ee848c2af27", "name":"username", "roles":[]}'
Note you need to apparently namespace the user name with the "org.couchdb.user" prefix. I used a Ruby hashing method to get the hashed_password value:
require 'digest/sha1'
pass_hash = Digest::SHA1.hexdigest(password)
This gets an apparently valid user into the database. The next step is to assign that user as a "writer" (ha, there it is again!) for the new database that I created. So I might do something like:
curl -X PUT http://admin:password#localhost:5984/newdatabase
and then
curl -X PUT http://admin:password#localhost:5984/newdatabase/_design/security -d #security.json
That .json file contains a Javascript function for the "validate_doc_update" key, and that function looks like this:
function(new_doc, old_doc, userCtx) {
if(userCtx.name != username) {
throw({forbidden: "Please log in first."});
}
}
It's roundabout, but it makes sense. However, I now am running into a problem: apparently the userCtx variable doesn't get populated until the user is authenticated. This article suggests that all you have to do is pass the credentials through an HTTP request to a special _session database, like so:
curl -X POST http://username:password#localhost:5984/_session
I can do that for my admin user, and the userCtx var will be populated. But for my newly-created user, it fails:
$ curl http://org.couchdb.user:username:password#localhost:5984/_session
{"ok":true,"userCtx":{"name":null,"roles":[]},"info":{"authentication_db":"_users","authentication_handlers":["cookie","oauth","default"]}}
Note the userCtx hash is null. I wonder if that namespace thing is causing the problem? It's got a freakin' colon in it, so maybe there's some confusion about the password? I've tried making it without the namespace, and it doesn't work at all; at least here my request appears to be hitting the database and getting a response.
I'm stuck at this point. If anyone can check my assumptions and progress thus far, I hope we can all figure out how to make this work.
Thanks!
Aaron.
You may want to check out Matt Woodward's - The Definitive Guide to CouchDB Authentication and Security http://blog.mattwoodward.com/2012/03/definitive-guide-to-couchdb.html

Resources