IBM Watson Speech-to-Text speech-javascript-sdk "HTTP Authentication failed; no valid credentials available" - ibm-cloud

I'm trying to set up IBM Watson Speech-to-Text to run in my Angular frontend. I'm using German Attanasio's speech-javascript-sdk library. I want the transcript text to go to the console so I'm using the microphone-streaming-object-to-console.html example. Here's my code:
const options = {
token: $scope.token,
model: 'en-US_BroadbandModel',
word_confidence: true,
object_mode: true
};
var stream = WatsonSpeech.SpeechToText.recognizeMicrophone(options);
The error I'm getting is
watson-speech.js:10482 WebSocket connection to 'wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize?model=en-US_BroadbandModel&watson-token=[object%20Object]' failed: HTTP Authentication failed; no valid credentials available
My guess is that my token isn't in the right format. The IAM bearer token is provided as a JSON object:
{
access_token: "eyJraWQiOiIyMDIwMDIyNTE4MjgiLCJhbGciOiJSUzI1NiJ9.e…",
expiration: 1585264266,
expires_in: 3600,
refresh_token: "OKA5toCaoVmYsPbwpjARE1971xspAe7Xg5nOm9pRrLKjKgaubr…",
scope: "ibm openid",
}
I tried providing the bare naked access_token, and I tried providing the JSON object. Both resulted in the same error message. Which format is correct?
Did I set up the options object correctly? Is it object_mode orobjectMode?
I don't understand what Object.assign(token, means in the example code.

I had the same problem and I found the solution working perfectly:
In 'options' constant you need to change the field 'token' by 'accessToken' and It should be works.
NOTE:
The field 'model' in 'options' has a default value, but if you want to change it you have to set value to 'model' and 'laguage',
const params = {
accessToken: 'token'
format: true,
extractResults: true,
objectMode: true,
model:'es-MX_BroadbandModel',
laguage: 'es-MX'
};

Related

jwt acess_token and refresh_token mechanism: axios : How to keep checking for the access_token is working

I am using JWT token based authentication system. i.e djangorestframework-simplejwt in my backend
Now I am using reactj and axios as frontend:
After providing username and pass to the login api, I got access_token and refresh_token which I stored in the localstorage
Now I am trying to connect to an api using access_token.
I get Token invalid or expired
Example I am trying to change password using this api and provide access_token
const url = "dj-rest-auth/password/change/";
const auth = {
headers: {
Authorization: "Bearer " + localStorage.getItem("access_token"),
Accept: "application/json",
"Content-Type": "application/json",
},
};
const data = {
old_password: old_password,
new_password1: new_password1,
new_password2: new_password2,
};
const promise = axios.post(url, data, auth);
promise
.then((res) => {
console.log(res)
})
.catch((err) => {
if (err.response) {
console.log(`${err.response.status} :: ${err.response.statusText}`)
console.log(err.response.data)
}
})
I can do another api call using refresh_token to get access_token when i get an err.
But sometimes, the err can be due to network error or something else. Then even i try to get access_token using refresh_token, it will just get into a loop.
HOw to do this the right way
If you are using Django as the backend, I would suggest using dj-rest-auth for JWT token authentication. dj-rest-auth requires "djangorestframework-simplejwt" for token management.
It is recommended to store access token and refresh token in httponly cookie so that it is not accessed by javascript.
Add JWTtokenAuthentication as authentication classes in settings.py.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'dj_rest_auth.jwt_auth.JWTCookieAuthentication'
]
}
Add the below configuration too in settings.py
REST_SESSION_LOGIN = False
SITE_ID=1
REST_USE_JWT = True
JWT_AUTH_COOKIE = 'access-token' #any name
JWT_AUTH_REFRESH_COOKIE = 'refresh_token' #any name
JWT_AUTH_SECURE = True
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
There is an open issue with dj-rest-auth, that requires the below code to be implemented in your back-end Github issue: https://github.com/iMerica/dj-rest-auth/issues/97. As workaround suggested, you have to create a file middleware.py and paste below code.
import json
from django.utils.deprecation import MiddlewareMixin
from yourapp.settings import JWT_AUTH_REFRESH_COOKIE # from settings.py
class MoveJWTRefreshCookieIntoTheBody(MiddlewareMixin):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, *view_args, **view_kwargs):
if request.path == '/token/refresh/' and JWT_AUTH_REFRESH_COOKIE in request.COOKIES:
if request.body != b'':
data = json.loads(request.body)
data['refresh'] = request.COOKIES[JWT_AUTH_REFRESH_COOKIE]
request._body = json.dumps(data).encode('utf-8')
else:
print("The incoming request body must be set to an empty object.")
return None
By now, your back-end will be successfully generating access token and refresh token. Even your back-end will be capable of refreshing access token using refresh token.
Front-End:
By default, access token and refresh tokens are stored in httponly cookie, so you don't need to worry about that part.
Axios can be used to make call to login-end point to get tokens. Make sure you use "withCredentials" and "Headers" in your request.
Response will be tokens, by default it will be stored in httponly cookie, since we are using dj-rest-auth. For all the consecutive requests, httponly cookie will be included, if tokens are valid, user will be provided access. IF token is expired, you need to make call to refresh endpoint to get new access token.
Since you are in development mode, you have to have same domain for both BE and FE, different ports.You can start django-server using below command and make sure your FE is also running in localhost
python manage.py runserver localhost:8080
dj-rest-auth : https://dj-rest-auth.readthedocs.io/en/latest/index.html

PostGraphile "invalid algorithm" error with RS256 encrypted JWT toaken

I'm using JWT verification with PostGraphile 4.6.0 in a node project. Here is the the code snippet:
createServer(
postgraphile(env.DATABASE_URL, "public", {
jwtVerifyAlgorithms: ["RS256"],
jwtSecret: "./publickey.pem",
jwtPgTypeIdentifier: "public.jwt_token",
rejectUnauthorized: false,
graphiql: true,
enhanceGraphiql: true,
graphqlRoute: env.POSTGRAPHILE_ROUTE + "/graphql",
graphiqlRoute: env.POSTGRAPHILE_ROUTE + "/graphiql",
})).listen(port, () => {
console.log("Listening at port:" + port);});
But when I use Postman to send RS256 encrypted JWT token, get error:
{
"errors": [
{
"message": "invalid algorithm"
}
]
}
And I created a function in Postgres to return JWT token, it always return HS256 encrypted JWT token. And I I use PostGraphile returned HS256 encrypted JWT token in Postman, JWT token is validated and the GrqphQL query returns fine.
Appears that the option "jwtVerifyAlgorithms" doesn't take effect.
Is there a way to make this work for RS256 encrypted JWT token?
Set the sign algorithm in jwtSignOptions
The following configuration should work:
{
...
jwtPublicKey: fs.readFileSync(process.env.PUBLIC_KEY_FILE_PATH, 'ascii'),
jwtSecret: fs.readFileSync(process.env.SECRET_KEY_FILE_PATH, 'ascii'),
jwtSignOptions: { algorithm: 'RS256' },
jwtTokenIdentifier: 'foo.bar',
jwtVerifyAlgorithms: ['RS256'],
...
}
The Postgraphile documentation states jwtPublicKey as the correct setting for providing the keys. Right now you are using jwtSecret with the string "./publickey.pem" which will not load the file, but instead use the file path as a password.
Make sure to load the file yourself using something like this:
...
jwtPublicKey: fs.readFileSync("./publickey.pem", "ascii")
...
Alternative via pgSettings
Worst case scenario you can also provide a custom pgSettings function that uses the jsonwebtoken npm library and verify the token yourself and write it to your settings.

can't exchange token manually v2.7

I'm using Loopback and
I'm trying to user auth for graph api without javascript sdk or passport
I got the code successfully however I can't exchange it with access token
I followed this guide https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/#confirm
my get request is https://graph.facebook.com/v2.7/dialog/oauth?code={xxxx}&client_secret={xxxx}&client_id={xxx}&redirect_uri={myURL}
myURL is the one used to get the code but not be used again if I understand
If I understand correctly I should it the access_token in the body of the response instead I get this error
{
"error": {
"message": "Unknown path components: /oauth",
"type": "OAuthException",
"code": 2500,
"fbtrace_id": "HXe+214tGpW"
}
}
It looks like a bug in the docs. The first call is to www.facebook.com in a browser.
See here for an example client https://github.com/yschimke/oksocial/blob/master/src/main/java/com/baulsupp/oksocial/services/facebook/FacebookAuthFlow.java
The second should be to something like https://graph.facebook.com/v2.7/oauth/access_token
$response = $fb->sendRequest(
'GET',
'/oauth/access_token',
[
'client_id' => $config['client_id'],
'client_secret' => $config['client_secret'],
'grant_type' => 'fb_exchange_token',
'fb_exchange_token' => $short_token
],
$short_token,
null,
'v2.7');

Trying to use 'Postman' and having trouble setting Basic access authentication Headers

I have an API endpoint that I am trying to test with the google app: 'Postman'. I need to set the headers which use 'Basic authentication'. I am not sure what should go in 'Header: Value'
This is how the admin said the headers should be set:
"The head value is the word 'Basic' followed by your org name and your Api key separated by a colon and base64 encoded."
I have tried numerous things but I am not getting it quite right. The error I get is "Message: Token not set".
Your header field should look like this:
Header : Authorization
Value : Basic base64('YourOrgName:YourAPIKEY');
You can get the base64 value of your string here:
https://www.base64encode.org/
For example, for my-org-name:123key4api it should be bXktb3JnLW5hbWU6MTIza2V5NGFwaQ==.
The complete header would look like:
Authorization: Basic bXktb3JnLW5hbWU6MTIza2V5NGFwaQ==
Looks like you are facing trouble in getting the base64 value. Well you can make use of in-built function in Javscript as below.
Simply run below code in any JS runtime, (Simplest would be - open console tab in chrome developer tool)
"username:password!" // Here I used basic Auth string format
// Encode the plain string to base64
btoa("username:password!"); // output: "dXNlcm5hbWU6cGFzc3dvcmQh"
// Decode the base64 to plain string
atob("dXNlcm5hbWU6cGFzc3dvcmQh"); // output: "username:password!"
It's 2019 and with Version 6.5.3 we have a separate tab to use different kind of Authentication techniques.
For basic auth you just have to give username and password after selecting "Basic Auth" under Authentication tab
Putting it all together in a pre-request script
(and then use the access_token for oauth).
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}};
var userPass = pm.environment.get("oauth_key") + ':' + pm.environment.get("oauth_secret")
pm.sendRequest({
url: pm.environment.get("basepath")+"/oauthpreview/token",
method: 'POST',
header: {
'Accept': 'application/json',
'cache-control':"no-cache",
'Authorization' : 'Basic ' + Base64.encode(userPass),
'Content-Type': 'application/x-www-form-urlencoded'
},
body: {
mode: 'urlencoded',
urlencoded: [
{key: "grant_type", value: "client_credentials", disabled: false}
]
}
}, function (err, res) {
pm.environment.set("access_token", res.json().access_token);
})

authenticating using a token in react

I am trying to GET some RESTful services using the api located at https://api.mmitnetwork.com
If I make a GET request it gives me a 401 error Unathorized. In order to authenticate using their api I am suppose to make a POST to https://api.mmitnetwork.com/Token with
{"grant_type":"password", "username":"yourusername","password":"yourpassword"}
in the body get a token.
How would I do this in react?
You can use axios: https://github.com/mzabriskie/axios
axios.post(' https://api.mmitnetwork.com/Token', {
grant_type: 'password',
username: 'yourusername',
password: 'yourpassword',
}).then((response) => {
console.log('success!')
}).catch((error) => {
console.log('something went wrong :(')
})