Hello,
I'm currently migrate API from v1 to v2, one of the big changes is the authentication flow. In v1 I using a secret key, passed through Authorization header during POST request. Value is encrypted with a strong encryption system (AWS KMS) and decrypted before being used.
Now, if I understand well, I need to use a JSON file.. I'm in a stateless environment so I haven't access to file system (and I don't want to save it to disk without encryption for obvious security reasons).
There is a method to pass credentials in a different way? Respect using an environment variable (GOOGLE_APPLICATION_CREDENTIALS) to point to a file on disk, for example a secret/access keys pair. An option in class constructor would be preferable instead of forcing to use an environment variable, maybe I can't even use them for example in Lambda@Edge ecosystem.
Being that file a simple JSON file it should not be so complicated to accept that values as javascript object, something like this:
const sessionClient = new dialogflow.SessionsClient({
"type": "service_account",
"project_id": "xxxxxxxxxx
"private_key_id": "xxxxxxxxxx",
"private_key": "-----BEGIN PRIVATE KEY-----\n....\n-----END PRIVATE KEY-----\n",
"client_email": "[email protected]",
"client_id": "xxxxxxxxxxxxxxxxxxxxxxx",
});
this will let developer to choice how to store values (environment variable/hashicorp vault/aws secret manager..etc..etc..) and most importantly, encrypted.
PS: using files to store configurations is an anti-pattern for 12 factor applications, this require to include that file under-version control (terrible) or creating it during build pipeline (this generate an non-agnostic artifact and is a bad practice IMHO) and cannot be tested locally.
You should be able to pass the contents of the .json file to the SessionsClient constructor on the credentials property like so:
const sessionClient = new dialogflow.SessionsClient({ credentials: { /* the json */ } })
For reference, this is the documentation for the constructor of the SessionsClient:
/**
* Construct an instance of SessionsClient.
*
* @param {object} [options] - The configuration object. See the subsequent
* parameters for more details.
* @param {object} [options.credentials] - Credentials object.
* @param {string} [options.credentials.client_email]
* @param {string} [options.credentials.private_key]
* @param {string} [options.email] - Account email address. Required when
* using a .pem or .p12 keyFilename.
* @param {string} [options.keyFilename] - Full path to the a .json, .pem, or
* .p12 key downloaded from the Google Developers Console. If you provide
* a path to a JSON file, the projectId option below is not necessary.
* NOTE: .pem and .p12 require you to specify options.email as well.
* @param {number} [options.port] - The port on which to connect to
* the remote host.
* @param {string} [options.projectId] - The project ID from the Google
* Developer's Console, e.g. 'grape-spaceship-123'. We will also check
* the environment variable GCLOUD_PROJECT for your project ID. If your
* app is running in an environment which supports
* {@link https://developers.google.com/identity/protocols/application-default-credentials Application Default Credentials},
* your project ID will be detected automatically.
* @param {function} [options.promise] - Custom promise module to use instead
* of native Promises.
* @param {string} [options.apiEndpoint] - The domain name of the
* API remote host.
*/
constructor(opts?: ClientOptions);
Hi @OlenDavis,
I try to retrieve the encrypted file content and passing to credentials parameters:
// retrieve file content from AWS Secret Manager
const secretResponse = await secretsManager.getSecretValue({
SecretId: event.SecretId
}).promise()
// parse response
const parameters = {
credentials: JSON.parse(secretResponse.SecretString)
}
// log for debug purpose (just to show you the correct parsed file)
console.log(parameters)
// set credentials parameters
const sessionClient = new dialogflow.SessionsClient(parameters)
file content is correctly formatted as the console.log show:
{ credentials:
{ type: 'service_account',
project_id: 'myproject-xxxx,
private_key_id: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
private_key:
'-----BEGIN PRIVATE KEY-----\n
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
\n-----END PRIVATE KEY-----\n',
client_email: '[email protected]',
client_id: 'xxxxxxxxxxxxxxxxxxxxxxxxxxx',
auth_uri: 'https://accounts.google.com/o/oauth2/auth',
token_uri: 'https://oauth2.googleapis.com/token',
auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs',
client_x509_cert_url:
'https://www.googleapis.com/robot/v1/metadata/x509/myproject-xxxxxxxxxx.iam.gserviceaccount.com' } }
but client raise an error:
{
"errorType": "Error",
"errorMessage": "Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.",
"stack": [
"Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.",
" at GoogleAuth.getApplicationDefaultAsync (/var/task/node_modules/google-auth-library/build/src/auth/googleauth.js:160:19)",
" at process._tickCallback (internal/process/next_tick.js:68:7)"
]
}
seems credentials are not correctly loaded.
Using dialogflow with this version:
$ npm list | grep "dialogflow"
├─┬ [email protected]
on Node 10.x
This issue might no longer be relevant due to its age. Feel free to re-open.
Most helpful comment
You should be able to pass the contents of the
.jsonfile to the SessionsClient constructor on thecredentialsproperty like so:For reference, this is the documentation for the constructor of the SessionsClient: