oracledb
Version:
A Node.js module for Oracle Database access from JavaScript and TypeScript
175 lines (163 loc) • 7.01 kB
JavaScript
// Copyright (c) 2025, Oracle and/or its affiliates.
//-----------------------------------------------------------------------------
//
// This software is dual-licensed to you under the Universal Permissive License
// (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
// 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
// either license.
//
// If you elect to accept the software under the Apache License, Version 2.0,
// the following applies:
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-----------------------------------------------------------------------------
;
const oracledb = require('oracledb');
const identitydataplane = require("oci-identitydataplane");
const common = require("oci-common");
const { generateKeyPair } = require('crypto');
const fs = require('fs');
async function getToken(params) {
switch (params.authType.toLowerCase()) {
case 'configfilebasedauthentication':
return await configFileBasedAuthentication(params);
case 'simpleauthentication':
return await simpleAuthentication(params);
default:
throwErr(`Invalid authentication type ${params.authType} in extensionOci plugins.`);
}
}
//---------------------------------------------------------------------------
// throwErr()
//---------------------------------------------------------------------------
function throwErr(message) {
throw new Error(message);
}
//---------------------------------------------------------------------------
// Generates a public-private key pair for proof of possession when token
// requested by this provider is presented for validation.
//---------------------------------------------------------------------------
async function _getKeyPair() {
return await new Promise((resolve, reject) => {
generateKeyPair('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
}
}, (err, publicKey, privateKey) => {
if (err) return reject(err);
resolve({publicKey, privateKey});
});
});
}
//---------------------------------------------------------------------------
// User defined function for reading token and private key values
// generated by the OCI SDK.
// Returns the OCI SDK's token request details object for the given
// config parameters, where a scope parameter specifies the
// scope of requested access. The request will specify a public key
// as being paired with a private key that the presenter of the token must
// prove to be in possession of.
//---------------------------------------------------------------------------
async function configFileBasedAuthentication(accessTokenConfig) {
const provider =
new common.ConfigFileAuthenticationDetailsProvider(accessTokenConfig.configFileLocation, accessTokenConfig.profile);
const client = new identitydataplane.DataplaneClient({authenticationDetailsProvider: provider});
const keyPair = await _getKeyPair();
const generateScopedAccessTokenDetails = {
scope: "urn:oracle:db::id::*",
publicKey: keyPair.publicKey
};
const generateScopedAccessTokenRequest = {
generateScopedAccessTokenDetails: generateScopedAccessTokenDetails
};
const generateScopedAccessTokenResponse =
await client.generateScopedAccessToken(generateScopedAccessTokenRequest);
const obj = {
token: generateScopedAccessTokenResponse.securityToken.token,
privateKey: keyPair.privateKey
};
return obj;
}
//---------------------------------------------------------------------------
// simpleAuthentication()
//---------------------------------------------------------------------------
async function simpleAuthentication(accessTokenConfig) {
const tenancy = accessTokenConfig.tenancy ??
throwErr("Token based authentication config parameter tenancy is missing for simpleauthentication in extensionOci plugins.");
const user = accessTokenConfig.user ??
throwErr("Token based authentication config parameter user is missing for simpleauthentication in extensionOci plugins.");
const fingerprint = accessTokenConfig.fingerprint ??
throwErr("Token based authentication config parameter fingerprint is missing for simpleauthentication in extensionOci plugins.");
const passphrase = accessTokenConfig.passphrase |= null; // optional
const privateKeyLocation = accessTokenConfig.privateKeyLocation ??
throwErr("Token based authentication config parameter privateKeyLocation is missing for simpleauthentication in extensionOci plugins.");
const privateKey = fs.readFileSync(privateKeyLocation, 'utf-8'); // ~/.oci/oci_api_key.pem
const regionId = accessTokenConfig.regionId ?? // ex : us-ashburn-1
throwErr("Token based authentication config parameter regionId is missing for simpleauthentication in extensionOci plugins.");
let region;
const regionsList = common.Region.values();
regionsList.forEach(regions => {
if (regions.regionId === regionId) {
region = regions;
return;
}
});
const provider = new common.SimpleAuthenticationDetailsProvider(
tenancy,
user,
fingerprint,
privateKey,
passphrase,
region
);
const client = new identitydataplane.DataplaneClient({
authenticationDetailsProvider: provider
});
const keyPair = await _getKeyPair();
const generateScopedAccessTokenDetails = {
scope: "urn:oracle:db::id::*",
publicKey: keyPair.publicKey
};
const generateScopedAccessTokenRequest = {
generateScopedAccessTokenDetails: generateScopedAccessTokenDetails
};
const generateScopedAccessTokenResponse = await client.generateScopedAccessToken(
generateScopedAccessTokenRequest
);
const obj = {
token: generateScopedAccessTokenResponse.securityToken.token,
privateKey: keyPair.privateKey
};
return obj;
}
//---------------------------------------------------------------------------
// hookFn()
// hookFn will get registerd to driver while loading plugins.
//---------------------------------------------------------------------------
function hookFn(options) {
if (options.tokenAuthConfigOci) {
// eslint-disable-next-line no-unused-vars
options.accessToken = async function callbackFn(refresh, config) {
return await getToken(config);
};
options.accessTokenConfig = options.tokenAuthConfigOci;
}
}
oracledb.registerProcessConfigurationHook(hookFn);