Skip to content

Instantly share code, notes, and snippets.

@Venryx
Last active July 14, 2020 09:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Venryx/bfa9b69583638dfbf611a9f292721a75 to your computer and use it in GitHub Desktop.
Save Venryx/bfa9b69583638dfbf611a9f292721a75 to your computer and use it in GitHub Desktop.
How to get a Google auth-token for DialogFlow, entirely from front-end JavaScript
import {GetAccessToken, ClaimSet} from "./GoogleAuth";
const projectID = "XXXXXX";
// session-id can apparently be set to an arbitrary value, eg. "abcd1234-abcd-abcd-abcd-abcd12345678".
const sessionID = "XXXXXX";
const serviceAccountEmail = `XXXXXX@${projectID}.iam.gserviceaccount.com`;
const serviceAccountPrivateKey = `-----BEGIN PRIVATE KEY-----\nXXXXXX\n-----END PRIVATE KEY-----`;
export async function ConvertSpeechToText(audioData_str_opus: string): Promise<string> {
const claimSet = new ClaimSet(["https://www.googleapis.com/auth/cloud-platform"], serviceAccountEmail);
const accessToken = await GetAccessToken(claimSet, serviceAccountPrivateKey);
//const response = await fetch("https://console.dialogflow.com/api/v2proxy/sessions/${sessionID}:detectIntent", {
//const response = await fetch(`https://dialogflow.googleapis.com/v2beta1/projects/${projectID}/agent/sessions/${sessionID}:detectIntent?access_token=${accessToken}`, {
//const response = await fetch(`https://dialogflow.googleapis.com/v2beta1/projects/${projectID}/agent/sessions/${sessionID}:detectIntent?key=${accessToken}`, {
//const response = await fetch(`https://dialogflow.googleapis.com/v2/{session=projects/${projectID}/agent/sessions/${sessionID}}:detectIntent`, {
const response = await fetch(`https://dialogflow.googleapis.com/v2beta1/projects/${projectID}/agent/sessions/${sessionID}:detectIntent`, {
method: "POST",
headers: {
authorization: `Bearer ${accessToken}`,
"content-type": "application/json",
},
body: JSON.stringify({
queryInput: {
audioConfig: {
/*audioEncoding: "AUDIO_ENCODING_LINEAR_16",
sampleRateHertz: 48000,*/
audioEncoding: "AUDIO_ENCODING_OGG_OPUS",
sampleRateHertz: 16000,
languageCode: "en",
},
},
queryParams: {
timeZone: "America/Los_Angeles",
},
inputAudio: audioData_str_opus,
}),
});
const responseJSON = await response.json();
console.log("Got responseJSON: ", responseJSON);
const speechText = responseJSON.queryResult.queryText || "";
return speechText;
}
import {KJUR} from "jsrsasign";
export class ClaimSet {
constructor(scopes: string[], issuerEmail: string) {
this.scopes = scopes;
this.issuerEmail = issuerEmail;
//this.audienceURL = "https://accounts.google.com/o/oauth2/token";
this.audienceURL = "https://www.googleapis.com/oauth2/v4/token";
this.duration = 60 * 60 * 1000;
}
scopes: string[];
issuerEmail: string;
delegationEmail?: string;
audienceURL: string;
issuedAtTime?: number; // milliseconds since unix-epoch
duration: number; // milliseconds (one hour max)
ToSpecClaimSet() {
const issuedAtTime = this.issuedAtTime || Date.now();
const expireAtTime = issuedAtTime + this.duration;
return {
scope: this.scopes.join(" "),
iss: this.issuerEmail,
sub: this.delegationEmail,
aud: this.audienceURL,
iat: Math.floor(issuedAtTime / 1000),
exp: Math.floor(expireAtTime / 1000),
};
}
}
function GetAssertion(claimSet: ClaimSet, privateKey: string) {
var header = {alg: "RS256", typ: "JWT"};
//let jws = new KJUR.jws.JWS();
/*const prv = KEYUTIL.getKey(privateKey);
return KJUR.jws.JWS.sign(header.alg, header, claimSet, prv);*/
return KJUR.jws.JWS.sign(header.alg, header, claimSet.ToSpecClaimSet(), privateKey);
}
export const claimSetPlusPK_cachedData = {} as {
[key: string]: {accessToken: string, cacheTime: number};
};
export async function GetAccessToken(claimSet: ClaimSet, privateKey: string) {
const claimSetPlusPK_json = JSON.stringify({claimSet, privateKey});
// if access-token is not cached, or cached token is expired (expires after 60m, but we get new one at 59m to be safe)
const cachedData = claimSetPlusPK_cachedData[claimSetPlusPK_json];
if (cachedData == null || Date.now() - cachedData.cacheTime > 59 * 60 * 1000) {
var assertion = GetAssertion(claimSet, privateKey);
const response = await fetch("https://www.googleapis.com/oauth2/v4/token", {
method: "POST",
headers: {
//"content-type": "application/x-www-form-urlencoded",
"content-type": "application/json",
},
//body: `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${assertion}`,
body: JSON.stringify({
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion,
}),
});
const responseJSON = await response.json();
console.log(`Got access token: ${responseJSON.access_token}`);
claimSetPlusPK_cachedData[claimSetPlusPK_json] = {accessToken: responseJSON.access_token, cacheTime: Date.now()};
}
return claimSetPlusPK_cachedData[claimSetPlusPK_json].accessToken;
}
@Emekaugo
Copy link

Emekaugo commented Jul 5, 2020

what is the code to Call GetAccessToken

@Venryx
Copy link
Author

Venryx commented Jul 5, 2020

@Emakaugo What do you mean? (The GetAccessToken function is defined at the bottom of the last file.)

@Emekaugo
Copy link

Emekaugo commented Jul 5, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment