"invalid signature" JWT Token Opentok - swift

I am trying to use the Opentok REST API with JWT to generate a video session token. I am using the following credentials to create the JWT following the JSONWebToken documentation at https://github.com/kylef/JSONWebToken.swift.
I have used the generated token for authorisation and followed the documentation at https://tokbox.com/developer/rest/#authentication and called the api from postman, but I am getting Invalid Signature error message. Where am i wrong?
var claims = ClaimSet()
claims["iss"] = "3*****2"
claims["ist"] = "account"
claims["iat"] = (Calendar.current.date(byAdding: .minute, value: 330, to: Date())?.timeIntervalSince1970)!
claims["exp"] = (Calendar.current.date(byAdding: .minute, value: 334, to: Date())?.timeIntervalSince1970)!
claims["jti"] = "\(NSUUID.init())"
claims["aud"] = "www.example.com"
let jToken = JWT.encode(claims: claims, algorithm: .hs256("334******************************d5af".data(using: .utf8)!))
print(jToken)

Hi Ram you are calling the session/create rest api. This api requires a project level authentication, however from you claims it looks like you are trying to generate a account level token.
The iss should be your API Key/ Project Id and the ist should be the string project.
Let me know if this helps and works.

I'm sure you figured your issue out by now but the archive mode and p2p.preference are not supposed to be header attributes but part of the body as json

At the Value field of "X-OPENTOK-AUTH" you first have to Write: "Bearer " + token.
If it doesn't work try changing "X-OPENTOK-AUTH" with "Authorization".

Related

How can I a Google Api restful endpoint using service key?

I'm using postman to memic a restful api call and trying to access google sheets API end point. When I try to access my endpoint it returns:
{
"error": {
"code": 403,
"message": "The request is missing a valid API key.",
"status": "PERMISSION_DENIED"
}
}
which is fair enough as I did not use my API key. I created a service account and got a json file, but I plan to access using a rest endpoint so need to pass token in header but I'm not sure how.
I looked at the json file and wasn't sure what to extract in order to pass it for my rest call.
Has anyone been able to do this successfully?
Before calling Google Services from Postman, you would need to re-create the flow for getting an access token form service account credentials :
build and encode the JWT payload from the data from credentials files (to populate aud, iss, sub, iat and exp)
request an access token using that JWT
make the request to the API using this access token
You can find a complete guide for this flow is located here: https://developers.google.com/identity/protocols/oauth2/service-account#authorizingrequests
Here is an example in python. You will need to install pycrypto and pyjwt to run this script :
import requests
import json
import jwt
import time
#for RS256 you may need this
#from jwt.contrib.algorithms.pycrypto import RSAAlgorithm
#jwt.register_algorithm('RS256', RSAAlgorithm(RSAAlgorithm.SHA256))
token_url = "https://oauth2.googleapis.com/token"
credentials_file_path = "./google.json"
#build and sign JWT
def build_jwt(config):
iat = int(time.time())
exp = iat + 3600
payload = {
'iss': config["client_email"],
'sub': config["client_email"],
'aud': token_url,
'iat': iat,
'exp': exp,
'scope': 'https://www.googleapis.com/auth/spreadsheets'
}
jwt_headers = {
'kid': config["private_key_id"],
"alg": 'RS256',
"typ": 'JWT'
}
signed_jwt = jwt.encode(
payload,
config["private_key"],
headers = jwt_headers,
algorithm = 'RS256'
)
return signed_jwt
with open(credentials_file_path) as conf_file:
config = json.load(conf_file)
# 1) build and sign JWT
signed_jwt = build_jwt(config)
# 2) get access token
r = requests.post(token_url, data= {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": signed_jwt.decode("utf-8")
})
token = r.json()
print(f'token will expire in {token["expires_in"]} seconds')
at = token["access_token"]
print(at)
Note the value of the scope: https://www.googleapis.com/auth/spreadsheets
Probably, you can do all the above flow using Google API library depending on what
programming language you prefer
The script above will print the access token :
ya29.AHES67zeEn-RDg9CA5gGKMLKuG4uVB7W4O4WjNr-NBfY6Dtad4vbIZ
Then you can use it in Postman in Authorization header as Bearer {TOKEN}.
Or using curl :
curl "https://sheets.googleapis.com/v4/spreadsheets/$SPREADSHEET_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"
Note: you can find an example of using service account keys to call Google translate API here

How to make a call to Firestore using gRPC

I'm trying to build a gRPC client for Google's Firestore API in Elixir.
Before starting to write some code , I thought that it would be wise to first start with BloomRPC in order to debug the issue.
As base url, I'm using https://firestore.googleapis.com where I pinned the rot certificate.
As auth I'm using an access_token obtained using oauth with the following 2 scopes: "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/datastore"
being passed as a Authorization header:
{
"Authorization": "Bearer 29ya.a0AfH6SMBDYZPsVgQv0PMqyGRXypc3DfWF_2jbvAJKMquTaryCvxEB7X1Rbprfk1Ebrwid2bXbcR3Aw-d1Tytlo_lThkyqRDRIbnSz5-nQ3xWklkmjyFMAuQtFCoz01hk3vbgBwd2gdbFNNWiOU_8NqPC_vElyz2-cQ34"
}
And I get back:
{
"error": "3 INVALID_ARGUMENT: Missing required project ID."
}
So clearly I should be passing the project ID somehow but I can't find it anywhere in the docs. Anybody any clues?
I just figured out what I was doing wrong.
Basically the Bearer token I was using is correct (obtained via the OAuth Playground).
The trick was to specify the PROJECT_ID in the parent parameter of the request:
{
"parent": "projects/[project-id]/databases/(default)/documents",
"page_size": 10
}
I should have just read the docs properly :)

How to open a JWT Token on Postman to put one of the claims value on a variable

To create a especific test on my application using Postman, after login and get the JWT token, I need to get a especific claim value to use in a variable in another POST on Postman.
Is that possible without develop a API to do it?
Thanks
Here is a simple function to do that.
let jsonData = pm.response.json();
// use whatever key in the response contains the jwt you want to look into. This example is using access_token
let jwtContents = jwt_decode(jsonData.access_token);
// Now you can set a postman variable with the value of a claim in the JWT
pm.variable.set("someClaim", jwtContents.payload.someClaim);
function jwt_decode(jwt) {
var parts = jwt.split('.'); // header, payload, signature
let tokenContents={};
tokenContents.header = JSON.parse(atob(parts[0]));
tokenContents.payload = JSON.parse(atob(parts[1]));
tokenContents.signature = atob(parts[2]);
// this just lets you see the jwt contents in the postman console.
console.log("Token Contents:\n" + JSON.stringify(tokenContents, null, 2));
return tokenContents;
}
The signature bit is still useless in this example, so you can not validate it with this, but it still addresses your question.
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("token", jsonData.token);
Follow the:
https://blog.postman.com/extracting-data-from-responses-and-chaining-requests/
I've created a request in Postman that 'logs in' and, then, the tests section of the response contains the following
var data = JSON.parse(responseBody);
postman.clearGlobalVariable("access_token");
postman.setGlobalVariable("access_token", data.access_token);
This puts the access token in a global variable so you can use it anywhere. If you're looking to read something from the JWT's claim, it's a bit more complicated.Check out how to add a library at https://github.com/postmanlabs/postman-app-support/issues/1180#issuecomment-115375864. I'd use the JWT decode library - https://github.com/auth0/jwt-decode .

OpenTok Rest Service Invalid JWT Error on Fiddler Request

I'm trying to create OpenTok session by Rest services with JWT object as suggested. I tried to generate session with Fiddler.
Here is my fiddler request (JWT string has been changed with *** partially for security reasons)
POST https: //api.opentok.com/session/create HTTP/1.1
Host: api.opentok.com
X-OPENTOK-AUTH: json_web_token
Accept: application/json
Content-Length: 172
eyJ0eXAiOiJKV1QiL******iOiJIUzI1NiJ9.eyJpc3MiOjQ1NzM******OiJkZW5l******XQiOjE0ODI3OTIzO***SOMESIGNEDKEYHERE***.izvhwYcgwkGCyNjV*****2HRqiyBIYi9M
I got 403 {"code":-1,"message":"Invalid token format"} error probably means my JWT object is not correct. I tried creating it using http://jwt.io (as opentok suggests) and other sites and all seems correct and very similar to the one on tokbox (opentok) site.
I need an explanation to fix it and create a session.
May it be because I am using opentok trial?
JWT creation Parameters
I had the same problem. I resolved the error by setting the correct key-value pairs for the payload part.
Example of my payload is as follows in C#:
var payload = new Dictionary<string, object>()
{
{ "iss", "45728332" },
{ "ist", "project" },
{ "iat", ToUnixTime(issued) },
{ "exp", ToUnixTime(expire) }
};
The value of the "ist" should be set to "project", not the actual name of your project.
Update: Looking at your screenshot, I can say you have not set the secret key (here, it's your ApiKeySecret from TokBox account > project) at the very bottom right.
OK I have found the answer at last,
Your Opentok API Secret key should not be used directly as Sign parameter. In java as shown below, it should be encoded first.
Base64.encodeToString("db4******b51a4032a83*******5d19a*****e01".getBytes(),0)
I haven't tried it on http://jwt.io and fiddler but it seems it will work on it too. Thanks. Full code is below;
payload = Jwts.builder()
.setIssuedAt(currentTime)
.setIssuer("YOUR_OPENTOK_KEY")
.setExpiration(fiveMinutesAdded)
.claim("ist", "project")
.setHeaderParam("typ","JWT")
.signWith(SignatureAlgorithm.HS256, Base64.encodeToString("YOUR_OPENTOK_SECRET".getBytes(),0))
.compact();
return payload;

using postman to access firebase REST API

I'm trying to use postman to do REST API calls to firebase. I've managed to read from firebase when my security rule is to permit all users including unauthorized ones.
but when I use this rule :
{"rules":{".read": "auth != null", ".write": "auth != null"}}
I get 'error' : 'permission denied' from postman.
I did the request token for google's web oauth2.0 client and got the authorization_code token back.
I tried to use token in the URL and in the header, tried it with GET & POST request and still get denied.
please help.
Thanks in advance
The answers above did not work for me.
What did work for me was going to
Project Settings (top left corner gear) -> Service Accounts (far right tab) -> Database Secrets (left menu) -> Scroll down, hover over the bulltets and click Show
Use this as the auth key, i.e. .../mycollection.json?auth=HERE
For me it worked like this:
https://your-database-url/users.json?auth=YOUR_AUTH_KEY
Where can you get this AUTH_KEY?
you get this key from your Project Settings -> Database -> Secret Key
Try something like this
https://your-database-url/users.json?auth=YOUR_AUTH_KEY
Respone is a JSON of your USERS node
I created a Postman pre-request script for helping create a Authentication: Bearer JWT. Should save a lot of copy pasting when testing APIs with Firebase Auth. https://gist.github.com/moneal/af2d988a770c3957df11e3360af62635
Copy of script at time of posting:
/**
* This script expects the global variables 'refresh_token' and 'firebase_api_key' to be set. 'firebase_api_key' can be found
* in the Firebase console under project settings then 'Web API Key'.
* 'refresh_token' as to be gathered from watching the network requests to https://securetoken.googleapis.com/v1/token from
* your Firebase app, look for the formdata values
*
* If all the data is found it makes a request to get a new token and sets a 'auth_jwt' environment variable and updates the
* global 'refresh_token'.
*
* Requests that need authentication should have a header with a key of 'Authentication' and value of '{{auth_jwt}}'
*
* Currently the nested assertions silently fail, I don't know why.
*/
pm.expect(pm.globals.has('refresh_token')).to.be.true;
pm.expect(pm.globals.has('firebase_api_key')).to.be.true;
var sdk = require('postman-collection'),
tokenRequest = new sdk.Request({
url: 'https://securetoken.googleapis.com/v1/token',
method: 'POST',
body: {
mode: 'urlencoded',
urlencoded: [{
type: 'text',
key: 'key',
value: pm.globals.get('firebase_api_key')
},
{
type: 'text',
key: 'grant_type',
value: 'refresh_token'
},
{
type: 'text',
key: 'refresh_token',
value: pm.globals.get('refresh_token')
},
]
}
});
pm.sendRequest(tokenRequest, function(err, response) {
pm.test('request for access token was ok', function() {
pm.expect(response).to.be.ok();
});
const json = response.json();
pm.expect(json).to.an('object');
pm.test('response json has needed properties', function() {
pm.expect(json).to.have.own.property('access_token');
pm.expect(json).to.have.own.property('token_type');
pm.expect(json).to.have.own.property('refresh_token');
const accessToken = json.access_token;
const tokenType = json.token_type;
const refreshToken = json.refresh_token;
pm.environment.set('auth_jwt', tokenType + ' ' + accessToken);
pm.globals.set('refresh_token', refreshToken);
});
});
Note: Adding this answer as all Options listed here is either deprecated or not working(mostly due to missing steps).
Best way to make it work with Postman is to use Google OAuth2 access tokens. The provided link described in full length but I have added quick steps.
Step 1: Download Service-Accounts.json
Step 2: Generate Access token in Java (provided link described support in other language for this)
make sure to include this dependency:
implementation 'com.google.api-client:google-api-client:1.25.0'
OR
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.25.0</version>
</dependency>
Run this code to generate token(Copied from google's javadocs)
// Load the service account key JSON file
FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountKey.json");
GoogleCredential scoped = GoogleCredential
.fromStream(serviceAccount)
.createScoped(
Arrays.asList(
"https://www.googleapis.com/auth/firebase.database",
"https://www.googleapis.com/auth/userinfo.email"
)
);
// Use the Google credential to generate an access token
scoped.refreshToken();
String token = scoped.getAccessToken();
System.out.println(token);
Step 3: Use the token in Postman
It is very simple to fetch data via Postman:
Here is how I did it
1 Your DB URL
https://YOUR_PROJECT_URL.firebaseio.com/YOUR_STRUCTURE/CLASS.json
2 Add API key in header as auth
auth = Value of your API_KEY
example:
We can use Firebase with postman for rest APIs
How we use Firebase in postman?
Copy your Firebase database URL
Paste it into your postman URL
Add .json at the last like shown in the image
Then play with your firebase database and make REST API