cache object
const cca = new msal.ConfidentialClientApplication({
auth: {
clientId: 'dummy data',
clientSecret: 'dummy data',
tokenCache: cache.storage.cache,
// tokenCache: tokenCache,
}
})
const account = await promiseConnection.query(accountQuery)
const buffer1 = Buffer.from(account[0][0].account, 'base64').toString()
const stringAccount = buffer1.toString();
const accountObject = JSON.parse(stringAccount)
// console.log(accountObject)
try {
const result = await cca.acquireTokenSilent({
scopes: ['calendars.readWrite'],
account: accountObject,
}).then(result => {
const accessToken = result.accessToken
console.log(accessToken)
})
} catch (error) {
console.log(error)
}`
I stored the token cache in a database and tried using it in the acquireTokenSilent() method.
I see the refresh token in the cache object, bit the error is:
errorCode: 'no_tokens_found',
errorMessage: 'No refresh token found in the cache. Please sign-in.',
Any advice?
Related
I am using a registered app to create/modify/upload folders and files one one drive business account through Graph API. I have everything set up and working when copying the AuthToken from Graph Explorer directly into my code. When I create the token in my code myself and I run my queries with my generated token I receive a Response Code 404 Not found. I will include my permissions below. Any help would be great, thank you!
const APP_ID ='xxxxxx';
const APP_SECERET = 'xxxxxx'
const TOKEN_ENDPOINT ='https://login.microsoftonline.com/b1a8639c-5c80-4ded-9347-d937b05848cb/oauth2/v2.0/token';
const MS_GRAPH_SCOPE = 'https://graph.microsoft.com/.default';
const postData = {
client_id: APP_ID,
scope: MS_GRAPH_SCOPE,
client_secret: APP_SECERET,
grant_type: 'client_credentials'
};
axios.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded';
let token = '';
function getToken () {
return new Promise((resolve, reject) => {
axios
.post(TOKEN_ENDPOINT, qs.stringify(postData))
.then(response => {
var access_token = response.data.access_token;
resolve();
console.log(access_token)
})
.catch(error => {
console.log(error);
});
}).catch(err => console.log(err))
}
// getToken()
oneDriveAPI.items.createFolder({
accessToken: accessToken,
rootItemId: "root",
name: "ssss"
}).then((item) => {
console.log(item)[enter image description here][1]
}).catch( (err) => {
console.log(err);
})
I am trying to collect twitter search results.
I am using twitter search API with Nodejs.
Started with "quick start" given in twitter api site https://developer.twitter.com/en/docs/labs/recent-search/quick-start, but I am keeping get errors from my request.
this is my code:
const https = require('https');
const request = require('request');
const util = require('util');
const get = util.promisify(request.get);
const post = util.promisify(request.post);
const consumer_key = 'xxxxxxx'; // Add your API key here
const consumer_secret = 'xxxxxx'; // Add your API secret key here
const bearerTokenURL = new URL('https://api.twitter.com/oauth2/token');
const searchURL = new URL('https://api.twitter.com/labs/2/tweets/search');
async function bearerToken (auth) {
const requestConfig = {
url: bearerTokenURL,
auth: {
user: consumer_key,
pass: consumer_secret,
},
form: {
grant_type: 'client_credentials',
},
};
const response = await post(requestConfig);
return JSON.parse(response.body).access_token;
}
(async () => {
let token;
const query = 'obama';
const maxResults = 10;
try {
// Exchange your credentials for a Bearer token
token = await bearerToken({consumer_key, consumer_secret});
} catch (e) {
console.error(`Could not generate a Bearer token. Please check that your credentials are correct and that the Filtered Stream preview is enabled in your Labs dashboard. (${e})`);
process.exit(-1);
}
const requestConfig = {
url: searchURL,
qs: {
query: query,
max_results: maxResults,
format: 'compact',
},
auth: {
bearer: token,
},
headers: {
'User-Agent': 'LabsRecentSearchQuickStartJS',
},
json: true,
};
try {
const res = await get(requestConfig);
console.log(res.statusCode);
console.log(res);
if (res.statusCode !== 200) {
throw new Error(res.json);
return;
}
console.log(res.json);
} catch (e) {
console.error(`Could not get search results. An error occurred: ${e}`);
process.exit(-1);
}
})();
my error:
body: {
errors: [ [Object] ],
title: 'Invalid Request',
detail: 'One or more parameters to your request was invalid.',
type: 'https://api.twitter.com/labs/2/problems/invalid-request' }, [Symbol(kCapture)]: false } Could not get search results. An
error occurred: Error
There's a bug in this script which we need to fix. If you remove the line format: 'compact', then this will work - that parameter is no longer valid in Labs v2.
I'm using a custom service account (using --service-account parameter in the deploy command). That service account has domain-wide delegation enabled and it's installed in the G Apps Admin panel.
I tried this code:
app.get('/test', async (req, res) => {
const auth = new google.auth.GoogleAuth()
const gmailClient = google.gmail({ version: 'v1' })
const { data } = await gmailClient.users.labels.list({ auth, userId: 'user#domain.com' })
return res.json(data).end()
})
It works if I run it on my machine (having the GOOGLE_APPLICATION_CREDENTIALS env var setted to the path of the same service account that is assigned to the Cloud Run service) but when it's running in Cloud Run, I get this response:
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Bad Request",
"reason" : "failedPrecondition"
} ],
"message" : "Bad Request"
}
I saw this solution for this same issue, but it's for Python and I don't know how to replicate that behaviour with the Node library.
After some days of research, I finally got a working solution (porting the Python implementation):
async function getGoogleCredentials(subject: string, scopes: string[]): Promise<JWT | OAuth2Client> {
const auth = new google.auth.GoogleAuth({
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
})
const authClient = await auth.getClient()
if (authClient instanceof JWT) {
return (await new google.auth.GoogleAuth({ scopes, clientOptions: { subject } }).getClient()) as JWT
} else if (authClient instanceof Compute) {
const serviceAccountEmail = (await auth.getCredentials()).client_email
const unpaddedB64encode = (input: string) =>
Buffer.from(input)
.toString('base64')
.replace(/=*$/, '')
const now = Math.floor(new Date().getTime() / 1000)
const expiry = now + 3600
const payload = JSON.stringify({
aud: 'https://accounts.google.com/o/oauth2/token',
exp: expiry,
iat: now,
iss: serviceAccountEmail,
scope: scopes.join(' '),
sub: subject,
})
const header = JSON.stringify({
alg: 'RS256',
typ: 'JWT',
})
const iamPayload = `${unpaddedB64encode(header)}.${unpaddedB64encode(payload)}`
const iam = google.iam('v1')
const { data } = await iam.projects.serviceAccounts.signBlob({
auth: authClient,
name: `projects/-/serviceAccounts/${serviceAccountEmail}`,
requestBody: {
bytesToSign: unpaddedB64encode(iamPayload),
},
})
const assertion = `${iamPayload}.${data.signature!.replace(/=*$/, '')}`
const headers = { 'content-type': 'application/x-www-form-urlencoded' }
const body = querystring.encode({ assertion, grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer' })
const response = await fetch('https://accounts.google.com/o/oauth2/token', { method: 'POST', headers, body }).then(r => r.json())
const newCredentials = new OAuth2Client()
newCredentials.setCredentials({ access_token: response.access_token })
return newCredentials
} else {
throw new Error('Unexpected authentication type')
}
}
What you can do here is define ENV variables in your yaml file as described in this documentation to set the GOOGLE_APPLICATION_CREDENTIALS to the path of the JSON key.
Then use a code such as the one mentioned here.
const authCloudExplicit = async ({projectId, keyFilename}) => {
// [START auth_cloud_explicit]
// Imports the Google Cloud client library.
const {Storage} = require('#google-cloud/storage');
// Instantiates a client. Explicitly use service account credentials by
// specifying the private key file. All clients in google-cloud-node have this
// helper, see https://github.com/GoogleCloudPlatform/google-cloud-node/blob/master/docs/authentication.md
// const projectId = 'project-id'
// const keyFilename = '/path/to/keyfile.json'
const storage = new Storage({projectId, keyFilename});
// Makes an authenticated API request.
try {
const [buckets] = await storage.getBuckets();
console.log('Buckets:');
buckets.forEach(bucket => {
console.log(bucket.name);
});
} catch (err) {
console.error('ERROR:', err);
}
// [END auth_cloud_explicit]
};
Or follow an approach similar to the one mentioned here.
'use strict';
const {auth, Compute} = require('google-auth-library');
async function main() {
const client = new Compute({
serviceAccountEmail: 'some-service-account#example.com',
});
const projectId = await auth.getProjectId();
const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`;
const res = await client.request({url});
console.log(res.data);
}
main().catch(console.error);
I am trying to execute the Cloud Bigtable to Cloud Storage SequenceFile template via REST API in a NodeJS backend server.
I am using axios 0.17.1 to send the request and I'm getting 401 status.
I tried to follow the google documentation however I couldn't figure out how to authorize an HTTP request to run a dataflow template.
I want to be authenticated as a service account and I successfully generated and dowloaded the json file containing the private key.
Can anyone help me by showing an example of sending HTTP POST request to https://dataflow.googleapis.com/v1b3/projects/[YOUR_PROJECT_ID]/templates:launch?gcsPath=gs://dataflow-templates/latest/
You need to generate a jwt from your service account credentials. The jwt can be exchanged for an access token which can then be used to make the request to execute the Dataflow job. Complete example:
import axios from "axios";
import jwt from "jsonwebtoken";
import mem from "mem";
import fs from "fs";
const loadServiceAccount = mem(function(){
// This is a string containing service account credentials
const serviceAccountJson = process.env.GOOGLE_APPLICATION_CREDENTIALS;
if (!serviceAccountJson) {
throw new Error("Missing GCP Credentials");
}
})
const loadCredentials = mem(function() {
loadServiceAccount();
const credentials = JSON.parse(fs.readFileSync("key.json").toString());
return {
projectId: credentials.project_id,
privateKeyId: credentials.private_key_id,
privateKey: credentials.private_key,
clientEmail: credentials.client_email,
};
});
interface ProjectCredentials {
projectId: string;
privateKeyId: string;
privateKey: string;
clientEmail: string;
}
function generateJWT(params: ProjectCredentials) {
const scope = "https://www.googleapis.com/auth/cloud-platform";
const authUrl = "https://www.googleapis.com/oauth2/v4/token";
const issued = new Date().getTime() / 1000;
const expires = issued + 60;
const payload = {
iss: params.clientEmail,
sub: params.clientEmail,
aud: authUrl,
iat: issued,
exp: expires,
scope: scope,
};
const options = {
keyid: params.privateKeyId,
algorithm: "RS256",
};
return jwt.sign(payload, params.privateKey, options);
}
async function getAccessToken(credentials: ProjectCredentials): Promise<string> {
const jwt = generateJWT(credentials);
const authUrl = "https://www.googleapis.com/oauth2/v4/token";
const params = {
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: jwt,
};
try {
const response = await axios.post(authUrl, params);
return response.data.access_token;
} catch (error) {
console.error("Failed to get access token", error);
throw error;
}
}
function buildTemplateParams(projectId: string, table: string) {
return {
jobName: `[job-name]`,
parameters: {
bigtableProjectId: projectId,
bigtableInstanceId: "[table-instance]",
bigtableTableId: table,
outputDirectory: `[gs://your-instance]`,
filenamePrefix: `${table}-`,
},
environment: {
zone: "us-west1-a" // omit or define your own,
tempLocation: `[gs://your-instance/temp]`,
},
};
}
async function backupTable(table: string) {
console.info(`Executing backup template for table=${table}`);
const credentials = loadCredentials();
const { projectId } = credentials;
const accessToken = await getAccessToken(credentials);
const baseUrl = "https://dataflow.googleapis.com/v1b3/projects";
const templatePath = "gs://dataflow-templates/latest/Cloud_Bigtable_to_GCS_Avro";
const url = `${baseUrl}/${projectId}/templates:launch?gcsPath=${templatePath}`;
const template = buildTemplateParams(projectId, table);
try {
const response = await axios.post(url, template, {
headers: { Authorization: `Bearer ${accessToken}` },
});
console.log("GCP Response", response.data);
} catch (error) {
console.error(`Failed to execute template for ${table}`, error.message);
}
}
async function run() {
await backupTable("my-table");
}
try {
run();
} catch (err) {
process.exit(1);
}
I followed this document https://firebase.google.com/docs/auth/web/facebook-login
token is a new accessToken given from the client
const context = ({req}) => {
const credential = firebase.auth.FacebookAuthProvider.credential(token)
try {
firebase.auth().signInAndRetrieveDataWithCredential(credential)
} catch(error) {
console.error(error)
}
}
but I'm receiving this error (100% sure the token is copied correctly)
{ [Error: Your API key is invalid, please check you have copied it correctly.]
code: 'auth/invalid-api-key',
message:
'Your API key is invalid, please check you have copied it correctly.' }
{ _extensionStack:
GraphQLExtensionStack { extensions: [ [CacheControlExtension] ] } }
Am I doing this wrong?
Found a solution!
On the client side I had to change the facebook accessToken into an IdToken via:
getIdToken = async () => {
const provider = new firebase.auth.FacebookAuthProvider()
const result = await firebase.auth().signInWithPopup(provider)
const IdToken = await firebase.auth().currentUser.getIdToken(true)
}
Then verify the IdToken in the backend
try {
const decodedToken = await admin.auth().verifyIdToken(token)
console.log(decodedToken)
} catch (error) {
// error code
}